#!/usr/bin/env python

import pyusblcd, time, string
from picolcd import PicoLcd
import thread, re
import datetime
import random
import os
import atexit
import RPi.GPIO as GPIO
import MySQLdb
import sys

sys.stdout = open("/var/log/regulator.log", "w", 0)

#prisotnost picolcd modula 20x2
PICOLCD = 1 
#shranjuje vrednosti senzorja v bazo
STORE = 1
#Vezava tipk na picoLCD modul
TIPKOVNICA = {'gor':'\x09\x00', 'dol':'\x03\x00', 'levo':'\x12\x00', 'desno':'\x06\x00', 'meni':'\x08\x00'}

if (PICOLCD == 1):
	usblcd = pyusblcd.UsbLCD()
else:
	usblcd = None
	
text0 = "Regulator"
text1 = "1.0"
pavza = 0
con1 = None
con2 = None
while (con1 == None or con2 == None):
	try:
		con1 = MySQLdb.connect(host='127.0.0.1', user='root', passwd='vr2etpb5', db='regulator')
		baza = con1.cursor()
		con2 = MySQLdb.connect(host='127.0.0.1', user='root', passwd='vr2etpb5', db='regulator')
		baza_store = con2.cursor()
	except Exception as e:
		print("MySQL tezava!")
		time.sleep(1)
mesalc = 0
program_trenutni = None
senzorji = []  
class senzor(object):
    def __init__(self, id, naziv, naslov, vrednost_1, vrednost_2, tip, vrednost):
		self.id = id
		self.naziv = naziv
		self.naslov = naslov
		self.vrednost_1 = vrednost_1		
		self.vrednost_2 = vrednost_2
		self.tip = tip
		self.vrednost = vrednost

programi = []  
class program(object):
    def __init__(self, program_id, senzor_id, vrednost, histereza, opis):
		self.program_id = program_id
		self.senzor_id = senzor_id
		self.vrednost = vrednost
		self.histereza = histereza
		self.opis = opis
		
# NASTAVITVE
baza.execute("SELECT * FROM `regulator`.`NASTAVITVE`")
nastavitve = baza.fetchall()
w1_prefix = nastavitve[0][0]
w1_suffix = nastavitve[0][1]
w1_regex = nastavitve[0][4]
w1_divide = nastavitve[0][5]
	
print "Nasel " + str(baza.execute("SELECT * FROM `regulator`.`SENZORJI`")) + " senzorjev"
for row in baza.fetchall():
	senzorji.append(senzor(row[0], row[1], row[2], row[3], row[4], row[5], None))

baza.execute("SELECT * FROM `regulator`.`PROGRAM_1`")
for row in baza.fetchall():
	programi.append(program(1, row[0], row[1], row[2], row[3]))
time.sleep(0.5)
baza.execute("SELECT * FROM `regulator`.`PROGRAM_2`")
for row in baza.fetchall():
	programi.append(program(2, row[0], row[1], row[2], row[3]))
time.sleep(0.5)
baza.execute("SELECT * FROM `regulator`.`PROGRAM_3`")
for row in baza.fetchall():
	programi.append(program(3, row[0], row[1], row[2], row[3]))
time.sleep(0.5)

# init sekvence
modfile = open("/proc/modules")
moduletext = modfile.read()
modfile.close()
if not (re.search("w1_gpio", moduletext) and re.search("w1_therm", moduletext)):
	os.system('sudo modprobe w1-gpio')
	os.system('sudo modprobe w1-therm')
	print "One-Wire modul omogocen!"

# GPIO nastavitve
GPIO.setwarnings(False)
GPIO.cleanup()
for senzor in senzorji:
	if (senzor.tip == 1):
		GPIO.setmode(GPIO.BCM)
		GPIO.setup(int(senzor.naslov), GPIO.OUT)
		GPIO.output(int(senzor.naslov), GPIO.HIGH)

def rele_mesalc(id_onof, id_smer, vrednost, delay):
	global mesalc
	if (mesalc == 0):
		
		mesalc = 1
		if (vrednost == 0 or vrednost=='-'):	#smer vrtenja
			GPIO.output(id_smer, GPIO.HIGH)
		else:
			GPIO.output(id_smer, GPIO.LOW)
		time.sleep(0.5)
		#print("VKLOP MESALCA V " + str(vrednost) + " " + str(id_onof))
		GPIO.output(id_onof, GPIO.LOW)	#vklopmo pompo za neskolko cajta
		time.sleep(delay)
		GPIO.output(id_onof, GPIO.HIGH)
		#print("IZKLOP MESALCA V " + str(vrednost))
		mesalc = 0
	
def pumpa(id_onof, vrednost):
	if (vrednost == 0 or vrednost=='-'):	#pumbo ugasnemo ali prizgemo
		GPIO.output(id_onof, GPIO.HIGH)
	else:
		GPIO.output(id_onof, GPIO.LOW)
		
def najdidan(dan):
	DNEVI = {0:'PON', 1:'TOR', 2:'SRE', 3:'CET', 4:'PET', 5:'SOB', 6:'NED'}
	return DNEVI[dan]
		
def najdisenzor(naziv):
	global senzorji
	for senzor in senzorji:
		if (senzor.naziv == naziv):
			return senzor
	
	
def status_zelena(status):
	if (PICOLCD):
		if (status == 'on' or status == 1):
			usblcd.setled(4,0)
		elif (status == 'off' or status == 0):
			usblcd.setled(4,1)
def status_rdeca(status):
	if (PICOLCD):
		if (status == 'on' or status == 1):
			usblcd.setled(5,0)
		elif (status == 'off' or status == 0):
			usblcd.setled(5,1)
			
status_zelena(0)       
status_rdeca(0)
	
# Zanka, ki poizveduje za vrednostmi in 
# - shranjuje vrednosti v graf
def getsensorvalues():
	global senzorji
	global w1_prefix
	global w1_suffix
	global baza
	global con1
	global baza_store
	global con2
	while (1):
		status_zelena(1)

		for senzor in senzorji:
			if (senzor.tip == 0):	# gre za w1 senzor
				try:
					poskus = 0
					while (1):
						file = open(w1_prefix + senzor.naslov + w1_suffix,'r')
						text = file.read()
						file.close()
						firstline  = text.split("\n")[0]
						crc_check = text.split("crc=")[1]
						crc_check = crc_check.split(" ")[1]
						if crc_check.find("YES")>=0:
							break
						else:
							poskus = poskus + 1
						if (poskus == 5):
							raise Exception("CRC se ne ujema!")
					secondline = text.split("\n")[1]                
					m = re.search(w1_regex, secondline)
					senzor.vrednost = round(float(m.groups()[0]) / float(w1_divide), 2)
				except Exception as e:
					senzor.vrednost = None
					#print "ALARM: branje senzorja w1: " + e.message
					status_rdeca(1)

			if (senzor.tip == 1):	# gre za gpio
				try:
					vrednost = GPIO.input(int(senzor.naslov))
					if vrednost == 1:
						senzor.vrednost = senzor.vrednost_1
					if vrednost == 0:
						senzor.vrednost = senzor.vrednost_2					
				except Exception as e:
					senzor.vrednost = None
					print "ALARM: senzor gpio: " + e.message
					status_rdeca(1)
					
			if (STORE == 1):	# vpis podatkov senzorja v bazo
				localtime   = time.localtime()
				cas = time.strftime("%Y-%m-%d %H:%M:%S", localtime)
				try:
					if (senzor.tip == 0):
						baza_store.execute("INSERT INTO `STOREDDATA` (`DATUM`, `SENSOR_ID`, `SENSOR_VALUE`) VALUES ('"+cas+"', "+str(senzor.id)+", "+str(senzor.vrednost)+");")
						con2.commit()
					elif (senzor.tip == 1):
						if (str(senzor.vrednost) == str(senzor.vrednost_1)):
							baza_store.execute("INSERT INTO `STOREDDATA` (`DATUM`, `SENSOR_ID`, `SENSOR_VALUE`) VALUES ('"+cas+"', "+str(senzor.id)+", 1);")
							con2.commit()
						else:
							baza_store.execute("INSERT INTO `STOREDDATA` (`DATUM`, `SENSOR_ID`, `SENSOR_VALUE`) VALUES ('"+cas+"', "+str(senzor.id)+", 0);")
							con2.commit()						
				except Exception as e:
					print "ALARM: store podatkov: " + e.message +" - "+str(senzor.id)+", "+str(senzor.vrednost)
					status_rdeca(1)
			
			time.sleep(2)
			
		status_zelena(0)
		time.sleep(10)

# zanka ki regulira izhode glede na senzorje
def regulacija():
	global baza
	global programi
	global program_trenutni
	global senzorji
	
	ura = datetime.datetime.now().strftime("%H")
	minute = datetime.datetime.now().strftime("%M")
	dan = najdidan(datetime.datetime.today().weekday())
	print("dan: " + dan + ", ura: " + ura)
	if (int(minute) < 30):
		baza.execute("SELECT `" + ura + ":00` FROM `regulator`.`SCHEDULER` WHERE `DAN` = '"+dan+"'")
	else:
		baza.execute("SELECT `" + ura + ":30` FROM `regulator`.`SCHEDULER` WHERE `DAN` = '"+dan+"'")
	program = str(baza.fetchall()[0][0])
	time.sleep(1)
	baza.execute("SELECT `OPIS` FROM `regulator`.`PROGRAMI` WHERE `INDEX` = "+program)
	program_opis = str(baza.fetchall()[0][0])
	print(dan + " " + ura + " " + minute + " - PROGRAM: " + program_opis)
	program_trenutni = program_opis
	
	for prog in programi:
		if (str(prog.program_id) == program):
			
			#print(prog.opis + " - " + str(prog.vrednost))
			pumpa_onoff = najdisenzor("crpalka")
			if (prog.opis == "Off"):
				pumpa(int(pumpa_onoff.naslov), "-")
			else:
				pumpa(int(pumpa_onoff.naslov), "+")
				
			if (prog.opis == "Temperatura dviznega voda"):
				mesalc_onoof = najdisenzor("ventil ogrevanja")
				mesalc_smer = najdisenzor("smer ogrevanja")
				senzor_forlauf = najdisenzor("dvizni vod")
				if (mesalc_onoof != None and mesalc_smer != None and senzor_forlauf != None):
					print("VREDNOST NASTAVLJENA: " + str(prog.vrednost) + " VREDNOST IZMERJENA: " + str(senzor_forlauf.vrednost))
					if (senzor_forlauf.vrednost != None):
						if (prog.vrednost > senzor_forlauf.vrednost):
							#print("Treba za " + str(float(prog.vrednost) - float(senzor_forlauf.vrednost)))
							thread.start_new_thread(rele_mesalc, (int(mesalc_onoof.naslov), int(mesalc_smer.naslov), "+", abs(float(prog.vrednost) - float(senzor_forlauf.vrednost))))
						else:
							#print("Treba za " + str(float(prog.vrednost) - float(senzor_forlauf.vrednost)))
							thread.start_new_thread(rele_mesalc, (int(mesalc_onoof.naslov), int(mesalc_smer.naslov), "-", abs(float(prog.vrednost) - float(senzor_forlauf.vrednost))))
						
	
# Zanka, ki prikazuje vrednosti na lcd 
def lcd_showsensorvalues():			
	global senzorji
	global pavza
	global program_trenutni
	while (1):
		for senzor in senzorji:	
			if (pavza == 0):
				usblcd.clear()
				time.sleep(0.2)
				usblcd.settext(0,0,str(senzor.naziv))
				time.sleep(0.2)
				usblcd.settext(1,0,str(senzor.vrednost))
				#print(str(senzor.naziv) + " " + str(senzor.vrednost))
				time.sleep(2)

		if (pavza == 0):
			usblcd.clear()
			time.sleep(0.2)
			usblcd.settext(0,0,"Program")
			usblcd.settext(1,0,str(program_trenutni))
			time.sleep(2)				
		
		if (pavza == 0):
			usblcd.clear()
			time.sleep(0.2)
			usblcd.settext(0,0,datetime.datetime.now().strftime("%Y-%m-%d %H:%M"))
			time.sleep(0.2)
			usblcd.settext(1,0,najdidan(datetime.datetime.today().weekday()))
			time.sleep(2)

def lcd_keyboardhandler():
	global pavza
	menu = ('Vrednosti', 'Nastavitve', 'Napake', 'Shrani', 'Izhod')

	while (1):
		i = 0
		t = usblcd.read_events()
		print(str(t[0]) + "-" + str(t[1]))
		if (t[0] == 0 and t[1] == TIPKOVNICA['meni']):
			pavza = 1
			t = (0,'')
			while (t[1] != TIPKOVNICA['meni']):
				usblcd.clear()
				usblcd.settext(0,0,str(i+1) + ". " + menu[i])
				t = usblcd.read_events()
				if (t[1] == TIPKOVNICA['levo'] and i > 0):
					i = i - 1
				if (t[1] == TIPKOVNICA['levo'] and i > len(menu)):
					i = i + 1                              
			if (i == 0):
				usblcd.clear()
				usblcd.settext(0,0,"POSKUS")        	



		



def keyboardhandler():
	global pavza
	menu = ('Vrednosti', 'Nastavitve', 'Napake', 'Shrani', 'Izhod')

	while (1):
		i = 0
		t = usblcd.read_events()
		if (t[0] == 0 and t[1] == TIPKOVNICA['meni']):
			pavza = 1
			t = (0,'')
			while (t[1] != TIPKOVNICA['meni']):
				usblcd.clear()
				usblcd.settext(0,0,str(i+1) + ". " + menu[i])
				t = usblcd.read_events()
				if (t[1] == TIPKOVNICA['levo'] and i > 0):
					i = i - 1
				if (t[1] == TIPKOVNICA['levo'] and i > len(menu)):
					i = i + 1				
			if (i == 0):
				usblcd.clear()
				usblcd.settext(0,0,"POSKUS")				
			
			
def exit_handler():
	status_zelena(0)
	status_rdeca(1)
	usblcd.clear()
	usblcd.settext(0,0,"NAPAKA!!")
	print "EXIT handler!"

atexit.register(exit_handler)

#Setup LCD


	
if (PICOLCD):
	usblcd.clear()
	status_zelena(0)
	status_rdeca(0)
	thread.start_new_thread(lcd_showsensorvalues,())
	#thread.start_new_thread(lcd_keyboardhandler,())


thread.start_new_thread(getsensorvalues,())




while(1):
	regulacija()
	time.sleep(3)
	

	






